<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
<title>Schedulers and Tasks</title>
<meta name="author" content="Philip Levis and Cory Sharp" />
<style type="text/css">

/*
:Author: David Goodger
:Contact: goodger@users.sourceforge.net
:date: $Date: 2009-02-03 23:07:32 $
:version: $Revision: 1.11 $
:copyright: This stylesheet has been placed in the public domain.

Default cascading style sheet for the HTML output of Docutils.
*/
body {
  font-family: Times;
  font-size: 16px;
}

.first {
  margin-top: 0 ! important }

.last {
  margin-bottom: 0 ! important }

.hidden {
  display: none }

a.toc-backref {
  text-decoration: none ;
  color: black }

blockquote.epigraph {
  margin: 2em 5em ; }

dd {
  margin-bottom: 0.5em }

div.abstract {
  margin: 2em 5em }

div.abstract p.topic-title {
  font-weight: bold ;
  text-align: center }

div.attention, div.caution, div.danger, div.error, div.hint,
div.important, div.note, div.tip, div.warning, div.admonition {
  margin: 2em ;
  border: medium outset ;
  padding: 1em }

div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
  color: red ;
  font-weight: bold ;
  font-family: sans-serif }

div.hint p.admonition-title, div.important p.admonition-title,
div.note p.admonition-title, div.tip p.admonition-title,
div.admonition p.admonition-title {
  font-weight: bold ;
  font-family: sans-serif }

div.dedication {
  margin: 2em 5em ;
  text-align: center ;
  font-style: italic }

div.dedication p.topic-title {
  font-weight: bold ;
  font-style: normal }

div.figure {
  margin-left: 2em }

div.footer, div.header {
  font-size: smaller }

div.line-block {
  display: block ;
  margin-top: 1em ;
  margin-bottom: 1em }

div.line-block div.line-block {
  margin-top: 0 ;
  margin-bottom: 0 ;
  margin-left: 1.5em }

div.sidebar {
  margin-left: 1em ;
  border: medium outset ;
  padding: 0em 1em ;
  background-color: #ffffee ;
  width: 40% ;
  float: right ;
  clear: right }

div.sidebar p.rubric {
  font-family: sans-serif ;
  font-size: medium }

div.system-messages {
  margin: 5em }

div.system-messages h1 {
  color: red }

div.system-message {
  border: medium outset ;
  padding: 1em }

div.system-message p.system-message-title {
  color: red ;
  font-weight: bold }

div.topic {
  margin: 2em }

h1 {
  font-family: Arial, sans-serif;
  font-size: 20px;
}

h1.title {
 text-align: center;
 font-size: 32px;
}

h2 {
 font-size: 16px;
 font-family: Arial, sans-serif;
}

h2.subtitle {
  text-align: center }

h3 {
 font-size: 12px;
 font-family: Arial, sans-serif;
}

hr {
  width: 75% }

ol.simple, ul.simple {
  margin-bottom: 1em }

ol.arabic {
  list-style: decimal }

ol.loweralpha {
  list-style: lower-alpha }

ol.upperalpha {
  list-style: upper-alpha }

ol.lowerroman {
  list-style: lower-roman }

ol.upperroman {
  list-style: upper-roman }

p.attribution {
  text-align: right ;
  margin-left: 50% }

p.caption {
  font-style: italic }

p.credits {
  font-style: italic ;
  font-size: smaller }

p.label {
  white-space: nowrap }

p.rubric {
  font-weight: bold ;
  font-size: larger ;
  color: maroon ;
  text-align: center }

p.sidebar-title {
  font-family: sans-serif ;
  font-weight: bold ;
  font-size: larger }

p.sidebar-subtitle {
  font-family: sans-serif ;
  font-weight: bold }

p.topic-title {
  font-weight: bold }

pre.address {
  margin-bottom: 0 ;
  margin-top: 0 ;
  font-family: serif ;
  font-size: 100% }

pre.line-block {
  font-family: serif ;
  font-size: 100% }

pre.literal-block, pre.doctest-block {
  margin-left: 2em ;
  margin-right: 2em ;
  background-color: #eeeeee;
  border-color: #000000;
  border-width: thin; 
  font-size: 14px
}

span.classifier {
  font-family: sans-serif ;
  font-style: oblique }

span.classifier-delimiter {
  font-family: sans-serif ;
  font-weight: bold }

span.interpreted {
  font-family: sans-serif }

span.option {
  white-space: nowrap }

span.option-argument {
  font-style: italic }

span.pre {
  white-space: pre }

span.problematic {
  color: red }

table {
  margin-top: 0.5em ;
  margin-bottom: 0.5em }

table.citation {
  border-left: solid thin gray ;
  padding-left: 0.5ex }

table.docinfo {
  margin: 2em 4em;
}

table.footnote {
  border-left: solid thin black ;
  padding-left: 0.5ex }

td, th {
  padding-left: 0.5em ;
  padding-right: 0.5em ;
  vertical-align: top }

th.docinfo-name, th.field-name {
  font-weight: bold ;
  text-align: left ;
  white-space: nowrap;
  }

h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
  font-size: 100% }

tt {}

ul.auto-toc {
  list-style-type: none }

</style>
</head>
<body>
<div class="document" id="schedulers-and-tasks">
<h1 class="title">Schedulers and Tasks</h1>
<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
<tr class="field"><th class="docinfo-name">TEP:</th><td class="field-body">106</td>
</tr>
<tr class="field"><th class="docinfo-name">Group:</th><td class="field-body">Core Working Group</td>
</tr>
<tr class="field"><th class="docinfo-name">Type:</th><td class="field-body">Documentary</td>
</tr>
<tr><th class="docinfo-name">Status:</th>
<td>Final</td></tr>
<tr class="field"><th class="docinfo-name">TinyOS-Version:</th><td class="field-body">2.x</td>
</tr>
<tr><th class="docinfo-name">Author:</th>
<td>Philip Levis and Cory Sharp</td></tr>
</tbody>
</table>
<div class="note">
<p class="first admonition-title">Note</p>
<p class="last">This memo documents a part of TinyOS for the TinyOS Community, and
requests discussion and suggestions for improvements.  Distribution
of this memo is unlimited. This memo is in full compliance with
TEP 1.</p>
</div>
<div class="section">
<h1><a id="abstract" name="abstract">Abstract</a></h1>
<p>This memo documents the structure and implementation of tasks
and task schedulers in TinyOS 2.x.</p>
</div>
<div class="section">
<h1><a id="introduction" name="introduction">1. Introduction</a></h1>
<p>TinyOS has two basic computational abstractions: asynchronous events
and tasks. Early versions of TinyOS provided a single type of task --
parameter free -- and only a FIFO scheduling policy. While changing
the latter was possible, the incorporation of tasks into the nesC
language made it very difficult. Presenting task schedulers as a
TinyOS component enables much easier customization, and allowing tasks
to be presented as an interface enables extending the classes of tasks
available. TinyOS 2.0 takes both approaches, and this memo documents
the structure of how it does so as well as a simple mechanism that
greatly increases system dependability.</p>
</div>
<div class="section">
<h1><a id="tasks-and-the-scheduler-in-tinyos-1-x" name="tasks-and-the-scheduler-in-tinyos-1-x">2. Tasks and the Scheduler in TinyOS 1.x</a></h1>
<p>Tasks in TinyOS are a form of deferred procedure call (DPC) <a class="footnote-reference" href="#id5" id="id1" name="id1">[1]</a>, which
enable a program to defer a computation or operation until a later
time. TinyOS tasks run to completion and do not pre-empt one
another.  These two constraints mean that code called from tasks
runs synchonously with respect to other tasks. Put another way, tasks
are atomic with respect to other tasks <a class="footnote-reference" href="#id6" id="id2" name="id2">[2]</a>.</p>
<p>In TinyOS 1.x, the nesC language supports tasks through two
mechanisms, <tt class="docutils literal"><span class="pre">task</span></tt> declarations and <tt class="docutils literal"><span class="pre">post</span></tt> expressions:</p>
<pre class="literal-block">
task void computeTask() {
  // Code here
}
</pre>
<p>and:</p>
<pre class="literal-block">
result_t rval = post computeTask();
</pre>
<p>TinyOS 1.x provides a single kind of task, a parameter-free function,
and a single scheduling policy, FIFO. <tt class="docutils literal"><span class="pre">post</span></tt> expressions can return
FAIL, to denote that TinyOS was unable to post the task.  Tasks can be
posted multiple times. For example, if a task is posted twice in quick
succession and the first succeeds while the second fails, then the
task will be run once in the future; for this reason, even if a <tt class="docutils literal"><span class="pre">post</span></tt>
fails, the task may run.</p>
<p>The TinyOS 1.x scheduler is implemented as a set of C functions in the
file <tt class="docutils literal"><span class="pre">sched.c</span></tt>. Modifying the scheduler requires replacing or
changing this file. Additionally, as tasks are supported solely through
nesC <tt class="docutils literal"><span class="pre">task</span></tt> declarations and <tt class="docutils literal"><span class="pre">post</span></tt> expressions, which assume
a parameter-free function, modifying the syntax or capabilities of
tasks is not possible.</p>
<p>The task queue in TinyOS 1.x is implemented as a fixed size circular
buffer of function pointers. Posting a task puts the task's function
pointer in the next free element of the buffer; if there are no free
elements, the <tt class="docutils literal"><span class="pre">post</span></tt> returns fail. This model has several issues:</p>
<blockquote>
<ol class="arabic simple">
<li>Some components do not have a reasonable response to a failed   post</li>
<li>As a given task can be posted multiple times, it can consume more than one element in the buffer</li>
<li>All tasks from all components share a single resource: one misbehaving component can cause other's posts to fail</li>
</ol>
</blockquote>
<p>Fundamentally, in order for a component A to repost a task after post
failure, another component B must call a function on it (either a
command or event). E.g., component A must schedule a timer, or expect
a retry from its client. However, as many of these systems might
depend on tasks as well (e.g., timers), it is possible that an
overflowing task queue can cause the entire system to fail.</p>
<p>The combination of the above three issues mean that one misbehaving
component can cause TinyOS to hang. Consider, for example, this
scenario (a real and encountered problem on the Telos platform):</p>
<blockquote>
<ul class="simple">
<li>A packet-based hardware radio, which issues an interrupt only when it finishes sending a packet</li>
<li>A networking component that handles the interrupt to post a task to signal <tt class="docutils literal"><span class="pre">SendMsg.sendDone</span></tt>.</li>
<li>A sensing component that posts a task when it handles an <tt class="docutils literal"><span class="pre">ADC.dataReady</span></tt> event</li>
<li>An application component that sends a packet and then sets its ADC sampling rate too high</li>
</ul>
</blockquote>
<p>In this scenario, the sensing component will start handling events at
a faster rate than it can process them. It will start posting tasks to
handle the data it receives, until it fills the task queue. At some
point later, the radio finishes sending a packet and signals its
interrupt. The networking component, however, is unable to post its
task that signals <tt class="docutils literal"><span class="pre">SendMsg.sendDone()</span></tt>, losing the event. The
application component does not try to send another packet until it
knows the one it is sending completes (so it can re-use the
buffer). As the <tt class="docutils literal"><span class="pre">sendDone()</span></tt> event was lost, this does not occur,
and the application stops sending network traffic.</p>
<p>The solution to this particular problem in TinyOS 1.x is to signal
sendDone() in the radio send complete interrupt if the post fails:
this violates the sync/async boundary, but the justification is that
a <em>possible</em> rare race condition is better than <em>certain</em> failure.
Another solution would be to use an interrupt source to periodically
retry posting the task; while this does not break the sync/async
boundary, until the post succeeds the system cannot send packets.
The TinyOS 1.x model prevents it from doing any better.</p>
</div>
<div class="section">
<h1><a id="tasks-in-tinyos-2-x" name="tasks-in-tinyos-2-x">3. Tasks in TinyOS 2.x</a></h1>
<p>The semantics of tasks in TinyOS 2.x are different than those in 1.x.
This change is based on experiences with the limitations and run time
errors that the 1.x model introduces. <strong>In TinyOS 2.x, a basic post will
only fail if and only if the task has already been posted and has not
started execution.</strong> A task can always run, but can only have one
outstanding post at any time.</p>
<p>2.x achieves these semantics by allocating one
byte of state per task (the assumption is that there will be fewer than 255
tasks in the system). While a very large number of tasks could make
this overhead noticable, it is not significant in practice.
If a component needs to post a task several times, then the end of
the task logic can repost itself as need be.</p>
<p>For example, one can do this:</p>
<pre class="literal-block">
post processTask();
...
task void processTask() {
  // do work
  if (moreToProcess) {
    post processTask();
  }
}
</pre>
<p>These semantics prevent several problems, such as the inability to
signal completion of split-phase events because the task queue is
full, task queue overflow at initialization, and unfair task
allocation by components that post a task many times.</p>
<p>TinyOS 2.x takes the position that the basic use case of tasks should
remain simple and easy to use, but that it should be possible to
introduce new kinds of tasks beyond the basic use case. TinyOS
achieves this by keeping <tt class="docutils literal"><span class="pre">post</span></tt> and <tt class="docutils literal"><span class="pre">task</span></tt> for the basic case,
and introducing task interfaces for additional ones.</p>
<p>Task interfaces allow users to extend the syntax and semantics of
tasks. Generally, a task interface has an <tt class="docutils literal"><span class="pre">async</span></tt> command,   post  ,
and an event, <tt class="docutils literal"><span class="pre">run</span></tt>. The exact signature of these functions are
up to the interface. For example, a task interface that allows a task
to take an integer parameter could look like this:</p>
<pre class="literal-block">
interface TaskParameter {
  async error_t command postTask(uint16_t param);
  event void runTask(uint16_t param);
}
</pre>
<p>Using this task interface, a component could post a task with a
<tt class="docutils literal"><span class="pre">uint16_t</span></tt> parameter. When the scheduler runs the task, it will
signal the <tt class="docutils literal"><span class="pre">runTask</span></tt> event with the passed parameter, which contains
the task's logic. Note, however, that this does not save any RAM:
the scheduler must have RAM allocated for the parameter.  Furthermore, as
there can only be one copy of a task outstanding at any time, it
is just as simple to store the variable in the component. E.g.,
rather than:</p>
<pre class="literal-block">
call TaskParameter.postTask(34);
...
event void TaskParameter.runTask(uint16_t param) {
  ...
}
</pre>
<p>one can:</p>
<pre class="literal-block">
uint16_t param;
...
  param = 34;
  post parameterTask();
...
task void parameterTask() {
  // use param
}
</pre>
<p>The principal difference between the simplest code for these
two models is that if the component posts the task twice, it
will use the older parameter in the TaskParameter example,
while it will use the newer parameter in the basic task example.
If a component wants to use the oldest parameter, then it can do
this:</p>
<pre class="literal-block">
if (post myTask() == SUCCESS) {
  param = 34;
}
</pre>
</div>
<div class="section">
<h1><a id="the-scheduler-in-tinyos-2-x" name="the-scheduler-in-tinyos-2-x">4. The Scheduler in TinyOS 2.x</a></h1>
<p>In TinyOS 2.x, the scheduler is a TinyOS component. Every scheduler
MUST support nesC tasks. It MAY also support any number of
additional task interfaces. The scheduler component is resonsible for
the policy of reconciling different task types (e.g., earliest
deadline first tasks vs. priority tasks).</p>
<p>The basic task in TinyOS 2.x is parameterless and FIFO. Tasks continue
to follow the nesC semantics of task and post, which are linguistic
shortcuts for declaring an  interface and wiring it to the
scheduler component. Appendix A describes how these shortcuts can be
configured. A scheduler provides a task interface as a parameterized
interface. Every task that wires to the interface uses the unique()
function to obtain a unique identifier, which the scheduler uses to
dispatch tasks.</p>
<p>For example, the standard TinyOS scheduler has this signature:</p>
<pre class="literal-block">
module SchedulerBasicP {
  provides interface Scheduler;
  provides interface TaskBasic[uint8_t taskID];
  uses interface McuSleep;
}
</pre>
<p>A scheduler MUST provide a parameterized TaskBasic interface.
If a call to TaskBasic.postTask() returns SUCCESS, the scheduler MUST run it
eventually, so that starvation is not a concern. The scheduler MUST
return SUCCESS to a TaskBasic.postTask()
operation unless it is not the first call to TaskBasic.postTask() since
that task's TaskBasic.runTask() event has been signaled. The
McuSleep interface is used for microcontroller power management;
its workings are explained in TEP 112 <a class="footnote-reference" href="#id7" id="id3" name="id3">[3]</a>.</p>
<p>A scheduler MUST provide the Scheduler interface.
The Scheduler interface has commands for initialization and running
tasks, and is used by TinyOS to execute tasks:</p>
<pre class="literal-block">
interface Scheduler {
  command void init();
  command bool runNextTask(bool sleep);
  command void taskLoop();
}
</pre>
<p>The init() command initializes the task queue and scheduler data
structures. runNextTask() MUST run to completion whatever task the
scheduler's policy decides is the next one: the return value indicates
whether it ran a task. The bool parameter sleep indicates what the
scheduler should do if there are no tasks to execute. If sleep is
FALSE, then the command will return immediately with FALSE as a return
value. If sleep is TRUE, then the command MUST NOT return until a task
is executed, and SHOULD put the CPU to sleep until a new task arrives.
Calls of runNextTask(FALSE) may return TRUE or FALSE; calls of
runNextTask(TRUE) always return TRUE.   The taskLoop() command tells
the scheduler to enter an infinite task-running loop, putting the MCU
into a low power state when the processor is idle: it never returns.</p>
<p>The scheduler is repsonsible for putting the processor to sleep
predominantly for efficiency reasons. Including the sleep call
within the scheduler improves the efficiency of the task loop,
in terms of the assembly generated by the TinyOS toolchain.</p>
<p>This is the TaskBasic interface:</p>
<pre class="literal-block">
interface TaskBasic {
  async command error_t postTask();
  void event runTask();
}
</pre>
<p>When a component declares a task with the <tt class="docutils literal"><span class="pre">task</span></tt> keyword in nesC, it
is implicitly declaring that it uses an instance of the TaskBasic
interface: the task body is the runTask event. When a component uses the
<tt class="docutils literal"><span class="pre">post</span></tt> keyword, it calls the postTask command. Each TaskBasic MUST be
wired to the scheduler with a unique identifier as its parameter.
The parameter MUST be obtained with the <tt class="docutils literal"><span class="pre">unique</span></tt> function in nesC,
with a key of <tt class="docutils literal"><span class="pre">&quot;TinySchedulerC.TaskBasic&quot;</span></tt>. The nesC compiler
automatically does this wiring when the <tt class="docutils literal"><span class="pre">task</span></tt> and <tt class="docutils literal"><span class="pre">post</span></tt>
keywords are used.</p>
<p>The SchedulerBasicP implementation uses these identifiers as its queue
entries. When TinyOS tells the scheduler to run a task, it pulls the
next identifier off the queue and uses it to dispatch on the
parameterized TaskBasic interface.</p>
<p>While the default TinyOS scheduler uses a FIFO policy, TinyOS
components MUST NOT assume a FIFO policy. If two tasks must run
in a particular temporal order, this order should be enforced by
the earlier task posting the later task.</p>
</div>
<div class="section">
<h1><a id="replacing-the-scheduler" name="replacing-the-scheduler">5. Replacing the Scheduler</a></h1>
<p>The TinyOS scheduler is presented as a component named TinySchedulerC.
The default TinyOS scheduler implementation is a module named
SchedulerBasicP; the default scheduler component is a configuration
that provides wire-through of SchedulerBasicP.</p>
<p>To replace the scheduler for a particular application, a developer
SHOULD put a configuration named TinySchedulerC in the application
directory: this will replace the default. The scheduler component
provides a wire-through of the desired scheduler implementation. All
scheduler implementations MUST provide a parameterize TaskBasic
interface, as SchedulerBasicP does; this supports nesC post statements
and task declarations and enables TinyOS core systems to operate
properly. Generally, TinyOS core code needs to be able to run unchanged
with new scheduler implementations.  All scheduler
implementations MUST provide the Scheduler interface.</p>
<p>For example, imagine a hypothetical scheduler that provides earliest
deadline first tasks, which are provided through the TaskEdf
interface:</p>
<pre class="literal-block">
interface TaskEdf {
  async command error_t postTask(uint16_t deadlineMs);
  event void runTask();
}
</pre>
<p>The scheduler implementation is named SchedulerEdfP, and provides both
TaskBasic and TaskEdf interfaces:</p>
<pre class="literal-block">
module SchedulerEdfP {
  provides interface Scheduler;
  provides interface TaskBasic[uint8_t taskID];
  provides interface TaskEdf[uint8_t taskID];
}
</pre>
<p>An application that wants to use SchedulerEdfP instead of
SchedulerBasicP includes a configuration named TinySchedulerC, which
exports all of SchedulerEdfP's interfaces:</p>
<pre class="literal-block">
configuration TinySchedulerC {
  provides interface Scheduler;
  provides interface TaskBasic[uint8_t taskID];
  provides interface TaskEdf[uint8_t taskID];
}
implementation {
  components SchedulerEdfP;
  Scheduler = SchedulerEdf;
  TaskBasic = SchedulerEdfP;
  TaskEDF   = SchedulerEdfP;
}
</pre>
<p>For a module to have an earliest deadline first task, it uses the
TaskEdf interface. Its configuration SHOULD wire it to TinySchedulerC.
The key used for task unique identifiers MUST be &quot;TinySchedulerC.TaskInterface&quot;,
where <em>TaskInterface</em> is the name of the new task interface as presented
by the scheduler.  A common way to make sure a consistent string is used
is to #define it. For example, TaskEdf.nc might include:</p>
<pre class="literal-block">
#define UQ_TASK_EDF &quot;TinySchedulerC.TaskEdf&quot;
</pre>
<p>In this example, the module SomethingP requires two EDF
tasks:</p>
<pre class="literal-block">
configuration SomethingC {
  ...
}
implementation {
  components SomethingP, TinySchedulerC;
  SomethingP.SendTask -&gt; TinySchedulerC.TaskEdf[unique(UQ_TASK_EDF)];
  SomethingP.SenseTask -&gt; TinySchedulerC.TaskEdf[unique(UQ_TASK_EDF)];
}
</pre>
<p>The module SomethingP also has a basic task. The nesC compiler
automatically transforms task keywords into BasicTask interfaces and
wires them appropriately. Therefore, for basic tasks, a component
author can either use the <tt class="docutils literal"><span class="pre">task</span></tt> and <tt class="docutils literal"><span class="pre">post</span></tt> keywords or use a TaskBasic
interface. A component SHOULD use the keywords whenever possible, and it
MUST NOT mix the two syntaxes for a given task.  This is an example
implementation of SomethingP that uses keywords for basic tasks:</p>
<pre class="literal-block">
module SomethingP {
  uses interface TaskEdf as SendTask
  uses interface TaskEdf as SenseTask
}
implementation {
  // The TaskBasic, written with keywords
  task void cleanupTask() { ... some logic ... }
  event void SendTask.runTask() { ... some logic ... }
  event void SenseTask.runTask() { ... some logic ... }

  void internal_function() {
    call SenseTask.postTask(20);
    call SendTask.postTask(100);
    post cleanupTask();
  }
}
</pre>
<p>The requirement that basic tasks not be subject to starvation
requires that a scheduler supporting EDF tasks must ensure that
basic tasks run eventually even if there is an unending stream of
short deadline tasks to run. Quantifying &quot;eventually&quot; is difficult,
but a 1% share of the MCU cycles (or invocations) is a reasonable
approximation.</p>
<p>If the scheduler provides two instances of the same task interface,
their unique keys are based on the name of the interface as the
scheduler presents it (the &quot;as&quot; keyword). For example, imagine
a scheduler which provides two instances of TaskBasic: standard
tasks and high-priority tasks. The scheduler usually selects a task
for the high priority queue before the standard queue:</p>
<pre class="literal-block">
configuration TinySchedulerC {
  provides interface Scheduler;
  provides interface TaskBasic[uint8_t taskID];
  provides interface TaskBasic[uint8_t taskID] as TaskHighPriority;
}
</pre>
<p>It cannot always select a high priority task because that could
starve basic tasks.  A component that uses a high priority task would
wire to TaskHighPriority with the key &quot;TinySchedulerC.TaskHighPriority&quot;:</p>
<pre class="literal-block">
configuration SomethingElseC {}
implementation {
  components TinySchedulerC as Sched, SomethingElseP;
  SomethingElseP.RetransmitTask -&gt; Sched.TaskHighPriority[unique(&quot;TinySchedulerC.TaskHighPriority&quot;)];
}
</pre>
</div>
<div class="section">
<h1><a id="implementation" name="implementation">6. Implementation</a></h1>
<p>The following files in <tt class="docutils literal"><span class="pre">tinyos-2.x/tos/system</span></tt> contain the reference
implementations of the scheduler:</p>
<blockquote>
<ul class="simple">
<li><tt class="docutils literal"><span class="pre">SchedulerBasicP.nc</span></tt> is the basic TinyOS scheduler, providing
a parameterized TaskBasic interface.</li>
<li><tt class="docutils literal"><span class="pre">TinySchedulerC.nc</span></tt> is the default scheduler configuration
that wires SchedulerBasicP to McuSleepC <a class="footnote-reference" href="#id7" id="id4" name="id4">[3]</a>.</li>
</ul>
</blockquote>
<p>A prototype of a scheduler that supports EDF tasks can be obtained
at the URL <tt class="docutils literal"><span class="pre">http://csl.stanford.edu/~pal/tinyos/edf-sched.tgz.</span></tt></p>
</div>
<div class="section">
<h1><a id="author-s-address" name="author-s-address">7. Author's Address</a></h1>
<div class="line-block">
<div class="line">Philip Levis</div>
<div class="line">358 Gates Hall</div>
<div class="line">Stanford University</div>
<div class="line">Stanford, CA 94305</div>
<div class="line"><br /></div>
<div class="line">phone - +1 650 725 9046</div>
<div class="line">email - <a class="reference" href="mailto:pal&#64;cs.stanford.edu">pal&#64;cs.stanford.edu</a></div>
<div class="line"><br /></div>
<div class="line">Cory Sharp</div>
<div class="line">410 Soda Hall</div>
<div class="line">UC Berkeley</div>
<div class="line">Berkeley, CA 94720</div>
<div class="line"><br /></div>
<div class="line">email - <a class="reference" href="mailto:cssharp&#64;eecs.berkeley.edu">cssharp&#64;eecs.berkeley.edu</a></div>
</div>
</div>
<div class="section">
<h1><a id="citations" name="citations">8. Citations</a></h1>
<table class="docutils footnote" frame="void" id="id5" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id1" name="id5">[1]</a></td><td>Erik Cota-Robles and James P. Held.  &quot;A Comparison of Windows
Driver Model Latency Performance on Windows NT and Windows 98.&quot; In
<em>Proceedings of the Third Symposium on Operating System Design
and Implementation (OSDI).</em></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="id6" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id2" name="id6">[2]</a></td><td>David Gay, Philip Levis, Rob von Behren, Matt Welsh, Eric Brewer
and David Culler. &quot;The <em>nesC</em> Language: A Holistic Approach to Networked
Embedded Systems.&quot; In <em>Proceedings of the ACM SIGPLAN 2003 Conference on
Programming Language Design and Implementation (PLDI).</em></td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="id7" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a name="id7">[3]</a></td><td><em>(<a class="fn-backref" href="#id3">1</a>, <a class="fn-backref" href="#id4">2</a>)</em> TEP 112: Microcontroller Power Management.</td></tr>
</tbody>
</table>
</div>
<div class="section">
<h1><a id="appendix-a-changing-the-scheduler" name="appendix-a-changing-the-scheduler">Appendix A: Changing the Scheduler</a></h1>
<p>The nesC compiler transforms the   post   and   task   keywords into
nesC interfaces, wirings, and calls. By default, the statement:</p>
<pre class="literal-block">
module a {
  ...
}
implementation {
  task x() {
    ...
    post x();
  }

}
</pre>
<p>is effectively:</p>
<pre class="literal-block">
module a {
  ...
  provides interface TaskBasic as x;
}
implementation {
  event void x.runTask() {
    ...
    call x.postTask();
  }
}
</pre>
<p>Specifically, TinyOS maps a task with name <em>T</em> to a TaskBasic
interface with name <em>T</em>. Posting <em>T</em> is a call to T.postTask(), and
the task body is T.runTask(). Finally, <em>T</em> is automatically wired to
TinySchedulerC with a unique() call.</p>
<p>While the fact that tasks are transformed into interfaces is built in
to the nesC compiler, the exact names can be configured. Each
platform's   .platform   file passes the   -fnesc-scheduler   option
to the compiler. The standard option is:</p>
<pre class="literal-block">
-fnesc-scheduler=TinySchedulerC,TinySchedulerC.TaskBasic,TaskBasic,TaskBasic,runTask,postTask
</pre>
<p>There are 6 strings passed. They are:</p>
<blockquote>
<ol class="arabic simple">
<li>The name of the scheduler component to wire the interface
to (TinySchedulerC).</li>
<li>The unique string used when wiring to the scheduler component's
parameterized interface (TinySchedulerC.TaskBasic).</li>
<li>The name of the interface on the scheduler component (TaskBasic).</li>
<li>The name of the interface type (TaskBasic).</li>
<li>The name of the event for running the task (runTask).</li>
<li>The name of the command for posting the task (postTask).</li>
</ol>
</blockquote>
<p>The nescc man page has further details.</p>
</div>
</div>
</body>
</html>
